using System;
using System.Diagnostics;
using System.Windows.Forms;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace S2Engine.Windows.Forms
{
    public partial class XnaControl : UserControl, IServiceProvider, IGraphicsDeviceService
    {
        #region Attributes
        GraphicsDevice device = null;
        double currentFrameTime = 0;
        double frameTime = 16.6;
        private bool isrunning;
        private CreateOptions createOptions = CreateOptions.SoftwareVertexProcessing;
        private GraphicsAdapter graphicsAdapter = GraphicsAdapter.DefaultAdapter;
        private Stopwatch stopWatch = new Stopwatch();
        private int fps = 60;

        private PictureBox pictureDesignLogo;
        //private GameServiceContainer services;
        //protected ContentManager content;
        //GraphicsDeviceManager graphics;
        #endregion

        #region Events
  
        public event EventHandler BeginLoad;
        public event EventHandler EndLoad;
        public event EventHandler BeginUpdate;
        public event EventHandler EndUpdate;
        public event EventHandler BeginDraw;
        public event EventHandler EndDraw;

        public virtual void OnBeginLoad()
        {
            if (BeginLoad != null)
                BeginLoad(this, EventArgs.Empty);
        }

        public virtual void OnEndLoad()
        {
            if (EndLoad != null)
                EndLoad(this, EventArgs.Empty);
        }

        public virtual void OnBeginUpdate()
        {
            if (BeginUpdate != null)
                BeginUpdate(this, EventArgs.Empty);
        }

        public virtual void OnEndUpdate()
        {
            if (EndUpdate != null)
                EndUpdate(this, EventArgs.Empty);
        }

        public virtual void OnBeginDraw()
        {
            if (BeginDraw != null)
                BeginDraw(this, EventArgs.Empty);
        }

        public virtual void OnEndDraw()
        {
            if (EndDraw != null)
                EndDraw(this, EventArgs.Empty);
        }

        #endregion

        public XnaControl()
        {
            //services = new GameServiceContainer();
            InitializeComponent();
            //services = new GameServiceContainer();
            //content = new ContentManager(services);
        }

        #region Properties
        public GraphicsDevice GraphicsDevice
        {
            get { return device; }
        }
        //public GameServiceContainer Services
        //{
        //    get { return services; }
        //}


        //public ContentManager Content
        //{
        //    get { return content; }
        //}

        public CreateOptions CreateOptions
        {
            get { return createOptions; }
            set { createOptions = value; }
        }

        public GraphicsAdapter GraphicsAdapter
        {
            get { return graphicsAdapter; }
            set { graphicsAdapter = value; }
        }

        public bool IsRunning
        {
            get { return isrunning; }
        }

        public int Fps
        {
            get { return fps; }
            set { fps = value; frameTime = 1000.0 / fps; }
        }
        #endregion

        #region Methods
        public void Run()
        {
            OnBeginLoad();
            Initialize();
            isrunning = true;
            this.pictureDesignLogo.Visible = false;
            OnEndLoad();
            UpdateGame();
        }

        protected virtual void Initialize()
        {
            //this.services = new GameServiceContainer();

            this.SetStyle(
                    ControlStyles.UserPaint |
                    ControlStyles.AllPaintingInWmPaint |
                    ControlStyles.Opaque, true);


            PresentationParameters pp = new PresentationParameters();
            pp.BackBufferCount = 1;
            pp.BackBufferFormat = SurfaceFormat.Unknown;
            pp.BackBufferHeight = this.Height;
            pp.BackBufferWidth = this.Width;
            pp.DeviceWindowHandle = this.Handle;
            pp.IsFullScreen = false;
            pp.MultiSampleType = MultiSampleType.None;
            pp.SwapEffect = SwapEffect.Discard;
            pp.PresentationInterval = PresentInterval.Immediate;
            device = new GraphicsDevice(graphicsAdapter, DeviceType.Hardware, this.Handle, createOptions, pp);

            //content = new ContentManager(Services);
        }

        public virtual void UpdateGame()
        {
            OnBeginUpdate();
            stopWatch.Reset();
            stopWatch.Start();
            //this.Invalidate();
            //Keyboard.Update();
            //UpdateSprite();
            //Render();

            stopWatch.Stop();
            currentFrameTime = (double)stopWatch.ElapsedMilliseconds;

            double delta = frameTime - currentFrameTime;
            //this.Parent.Text = m_FrameTime.ToString() + " - " + m_CurrentFrameTime.ToString() + " - " + delta.ToString(); ;

            if (delta > 0)
            {
                stopWatch.Reset();
                stopWatch.Start();
                while ((double)stopWatch.ElapsedTicks < delta) ;
                stopWatch.Stop();
                currentFrameTime += stopWatch.ElapsedTicks;
            }

            //elapsedFrames += 0.0001f;
            //this.Parent.Text = elapsedFrames.ToString();
            OnEndUpdate();
            Draw();
        }

        protected virtual void Draw()
        {
            device.Clear(new Microsoft.Xna.Framework.Graphics.Color(this.BackColor.R, this.BackColor.G, this.BackColor.B, this.BackColor.A));
            OnBeginDraw();
            ////device.Clear( ClearOptions.Target,Microsoft.Xna.Framework.Graphics.Color.Black,1.0f,0);
            //spriteBatch.Begin(SpriteBlendMode.None);
            //spriteBatch.Draw(myTexture, spritePosition, Microsoft.Xna.Framework.Graphics.Color.White);
            //spriteBatch.End();

            //device.Present();
        }

        public virtual void Present()
        {
            OnEndDraw();
            device.Present();
            this.Invalidate();
        }
        #endregion

        private void InitializeComponent()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(XnaControl));
            this.pictureDesignLogo = new System.Windows.Forms.PictureBox();
            ((System.ComponentModel.ISupportInitialize)(this.pictureDesignLogo)).BeginInit();
            this.SuspendLayout();
            // 
            // pictureDesignLogo
            // 
            this.pictureDesignLogo.Image = ((System.Drawing.Image)(resources.GetObject("pictureDesignLogo.Image")));
            this.pictureDesignLogo.Location = new System.Drawing.Point(25, 56);
            this.pictureDesignLogo.Name = "pictureDesignLogo";
            this.pictureDesignLogo.Size = new System.Drawing.Size(150, 59);
            this.pictureDesignLogo.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
            this.pictureDesignLogo.TabIndex = 0;
            this.pictureDesignLogo.TabStop = false;
            // 
            // XnaControl
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(71)))), ((int)(((byte)(105)))));
            this.Controls.Add(this.pictureDesignLogo);
            this.Name = "XnaControl";
            this.Size = new System.Drawing.Size(203, 174);
            this.Load += new System.EventHandler(this.XnaControl_Load);
            this.Resize += new System.EventHandler(this.XnaControl_Resize);
            ((System.ComponentModel.ISupportInitialize)(this.pictureDesignLogo)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        private void XnaControl_Resize(object sender, EventArgs e)
        {
            PositionateDesignLogo();
        }

        private void PositionateDesignLogo()
        {
            if (!isrunning)
            {
                this.pictureDesignLogo.Top = (this.Height / 2) - (pictureDesignLogo.Height / 2);
                this.pictureDesignLogo.Left = (this.Width / 2) - (pictureDesignLogo.Width / 2);
            }
        }

        private void XnaControl_Load(object sender, EventArgs e)
        {
            PositionateDesignLogo();
        }

        #region IGraphicsDeviceService Members

        public event EventHandler DeviceCreated;

        public event EventHandler DeviceDisposing;

        public event EventHandler DeviceReset;

        public event EventHandler DeviceResetting;

        #endregion

        #region IServiceProvider Members

        public object GetService(Type serviceType)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion
    }
}
